﻿using Core.Framework;
using Grain.State.BaseModule.StorgeStates;
using iTool.ClusterComponent;
using Orleans;
using Orleans.Runtime;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;

namespace Grain.Implements
{
    public class ReminderService : iToolServiceBase<RemindersServiceState>, Interfaces.IReminderService, IRemindable
    {
        public Task<ConcurrentDictionary<string, ReminderInfo>> GetReminderList()
        {
            return Task.FromResult(this.State.ReminderKeyValue);
        }


        public async Task DoSomethingThatTriggersReminder(string reminderName, string moduleName, double periodOfMinutes)
        {
            await RegisterOrUpdateReminder(reminderName, TimeSpan.FromSeconds(10), TimeSpan.FromMinutes(periodOfMinutes));

            ReminderInfo entity = new ReminderInfo();
            entity.ErrorInfo = string.Empty;
            entity.PeriodOfMinutes = periodOfMinutes;
            entity.FunctionModuleName = moduleName + "_module";
            entity.IsRunSuccess = false;
            entity.LastRunTime = default;
            entity.RegTime = DateTime.Now;

            this.State.ReminderKeyValue.AddOrUpdate(reminderName, entity, (key, value) => entity);

            await this.WriteStateAsync();
        }

        public async Task ReceiveReminder(string reminderName, TickStatus status)
        {
            this.State.ReminderKeyValue.TryGetValue(reminderName, out ReminderInfo entity);

            if (entity == null)
            {
                return;
            }

            object[] args = new object[] { new { } };
            var result = await NodeJS.InvokeAsync<dynamic>(entity.FunctionModuleName, args);

            entity.IsRunSuccess = result.IsFinished;
            entity.LastRunTime = DateTime.Now;

            if (!result.IsFinished)
            {
                entity.ErrorInfo = result.Discription;
            }

            await this.WriteStateAsync();

        }

        public async Task UnregisterReminder(string reminderName)
        {
            var reminder = await this.GetReminder(reminderName);

            if (reminder != null)
            {
                await UnregisterReminder(reminder);

                this.State.ReminderKeyValue.TryRemove(reminderName, out ReminderInfo entity);

                await this.WriteStateAsync();
            }
        }

        public Task<bool> IsExistByModulePath(string modulePath)
        {
            return Task.FromResult(this.State.ReminderKeyValue.Where(a => a.Value.FunctionModuleName.Equals(modulePath)).Count() > 0);
        }

        public Task<bool> IsExistByReminderName(string reminderName)
        {
            return Task.FromResult(this.State.ReminderKeyValue.ContainsKey(reminderName));
        }
    }
}
